package com.north.light.androidutils.looper;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import java.io.Serializable;
import java.util.HashMap;

/**
 * FileName: TimerUtil
 * Author: lzt
 * Date: 2022/8/8 09:51
 * 循环计时工具类(循环计时，单次延时)
 */
public class TimerUtil implements Serializable {

    private Handler mLooperHandler;

    private LooperCallback mCallback;

    private boolean mEnding = false;

    //标识集合
    private final HashMap<Integer, LooperMessage> mTaskMap = new HashMap<>();

    /**
     * 启动
     */
    public void start(String key) {
        start(key, 1000, true, false);
    }

    /**
     * 启动
     */
    public void start(String key, long time) {
        start(key, time, true, false);
    }

    /**
     * 启动
     *
     * @param key      关键字--不可重复
     * @param interval 时间间隔
     * @param now      是否立即执行
     * @param repeat   是否重复
     */
    public void start(String key, long interval, boolean now, boolean repeat) {
        if (interval <= 0 || TextUtils.isEmpty(key)) {
            return;
        }
        if (mEnding) {
            return;
        }
        //检查looper是否已经存在
        LooperMessage oldInterval = mTaskMap.get(key.hashCode());
        if (oldInterval != null) {
            //先移除旧逻辑
            stop(key);
        }
        //插入新looper
        mTaskMap.put(key.hashCode(), new LooperMessage(key, interval, repeat));
        if (mLooperHandler == null) {
            mLooperHandler = new Handler(Looper.myLooper()) {
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    int msgWhat = msg.what;
                    LooperMessage looperMessage = mTaskMap.get(msgWhat);
                    if (looperMessage != null) {
                        //存在数据，回调
                        if (mCallback != null) {
                            mCallback.looper(looperMessage.getKey(), looperMessage.getInterval());
                        }
                        //继续发送--判断是否重复
                        if (mLooperHandler != null && looperMessage.isRepeat()) {
                            mLooperHandler.sendEmptyMessageDelayed(looperMessage.getKey().hashCode(),
                                    looperMessage.getInterval());
                        }
                    }
                }
            };
        }
        //开始执行
        if (!now) {
            mLooperHandler.sendEmptyMessageDelayed(key.hashCode(), interval);
        } else {
            mLooperHandler.sendEmptyMessage(key.hashCode());
        }
    }


    /**
     * 停止--可以再次启动
     */
    public void stop() {
        if (mLooperHandler != null) {
            mLooperHandler.removeCallbacksAndMessages(null);
        }
    }

    public void stop(String key) {
        if (TextUtils.isEmpty(key)) {
            return;
        }
        if (mLooperHandler != null) {
            mLooperHandler.removeMessages(key.hashCode());
        }
    }

    /**
     * 结束--不能再次启动
     */
    public void end() {
        mEnding = true;
        stop();
        mTaskMap.clear();
    }

    /**
     * 监听
     */
    public void setLooperCallback(LooperCallback looperCallback) {
        this.mCallback = looperCallback;
    }

    public void removeLooperCallback() {
        this.mCallback = null;
    }

    public interface LooperCallback {
        public void looper(String key, long interval);
    }

    public static class LooperMessage implements Serializable {
        private String key;
        private long interval;
        private boolean repeat;

        public LooperMessage(String key, long interval, boolean repeat) {
            this.key = key;
            this.interval = interval;
            this.repeat = repeat;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public long getInterval() {
            return interval;
        }

        public void setInterval(long interval) {
            this.interval = interval;
        }

        public boolean isRepeat() {
            return repeat;
        }

        public void setRepeat(boolean repeat) {
            this.repeat = repeat;
        }
    }
}
